/**
 * @file   : init.c
 * @author : chenshucheng
 * @date   : 03/24/2021
 * @brief  : 测试框架
 * @note   : 
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "CUnit.h"
#include "Automated.h"
#include "Console.h"
#include "base_type.h"
#include "init.h"

/**
 * 测试套件信息结构体数组
 * 注册测试套件时用到
 * 添加测试套件时需要填写
 */
CU_SuiteInfo gUtSuites[UTITENUM] = {
    CU_SUITE_INFO_NULL
};

FwtCunitCfg_s gFwtUtCfg = {
    .flag = FWT_UT_RUN_INACTIVE,
    .runLoop = FWT_UT_RUNLOOP,
    .pCunitName = NULL,
};

/**
 * @brief   将测试结果综合打印到屏幕
 * @param:  [in]   无
 * @return  [out]  无
 * @warning 可重入
 * @note    新生成函数
 */
static void fwtPrintResults(void)
{
    S8 *pResult;
    
    pResult = CU_get_run_results_string();
    fprintf(stdout,"%s",pResult);
    
    return ;
}

/**
 * @brief   向测试注册表添加测试套件
 * @param:  [in]   无
 * @return  [out]  无
 * @warning 可重入
 * @note    新生成函数
 */
static int fwtAddTests(void)
{
    if (CU_register_suites(gUtSuites) != CUE_SUCCESS) {      ///< 注册测试套件 
        fprintf(stderr, "suite registration failed - %s\n",
        CU_get_error_msg());
        return -1;
    }
    return 0;
}

/**
 * @brief   初始化测试套件
 * @param:  [in]   SutSuitesM[]
 * @return  [out]  无
 * @warning 可重入
 * @note    新生成函数
 */
void fwtInitSuite(CU_SuiteInfo SutSuitesM[])
{
    U32 i = 0;
    U32 j = 0;    ///< 用来记录当前套件数组已有数量                      
    CU_SuiteInfo SutSuitesNULL = {NULL,NULL,NULL,NULL};

    for(i = 0;i<UTITENUM;i++) {
        if(gUtSuites[i].pName == NULL) {
            j = i;
            break;
        }
    }
    for(i = 0;i<UTITENUM;i++) {
        if(SutSuitesM[i].pName != NULL) {
            gUtSuites[j] = SutSuitesM[i];
            gUtSuites[(ULong)(j+1)] = SutSuitesNULL;
            j++;
        } else {
            break;
        }
    }
    
    return ;
}

/**
 * @brief   根据输入的参数来运行对应的套件
 * @param:  [in]   num 套件总数
 * @param:  [in]   argnum 参数总数
 * @param:  [in]   argv[] main函数的参数
 * @return  [out]  无
 * @warning 可重入
 * @note    新生成函数
 */
static void fwtRunSuite(U32 num, U32 argnum,char *argv[])
{    
    U32 i = 0;
    U32 k = 0;
    CU_pSuite pSuite[UTITENUM] = {NULL};

    for (i = 0;i<num;i++) {
        pSuite[i] = CU_get_suite(gUtSuites[i].pName);
        CU_set_suite_active(pSuite[i], INACTIVE);
        for (k = 0;k<argnum;k++) {
            if (strcmp(argv[k],gUtSuites[i].pName) == 0) {
                CU_set_suite_active(pSuite[i], ACTIVE);
            }
        }
    }
    
    return ;
}

/**
 * @brief    main函数参数处理
 * @param    mainArgc           [in],  main函数入参个数
 * @param    mainArgv           [in],  main函数实际入参
 * @param    mainArgvResolved   [in],  待匹配参数库
 * @return   待处理的参数
 */
int fwtUtGetopt(int mainArgc, S8 **ppMainArgv, const S8 *pMainArgvResolved)
{
    return getopt(mainArgc, ppMainArgv, pMainArgvResolved);
}

/**
 * @brief    main函数参数处理
 * @param    mainArgc       [in],  main函数入参个数
 * @param    mainArgv       [in],  main函数实际入参
 * @return   0：成功， < 0 : 失败
 */
int fwtUtArgvHandle(int mainArgc, S8 **ppMainArgv) 
{
    int ret          = 0;
    int mainArgvTemp = 0;

    if (NULL == ppMainArgv) {
        ret = -1;
        printf("para invalid !");
        goto end;
    }

    ///< TODO "vat",函数入参未来可以在"vat"基础上扩充
    while ((mainArgvTemp = fwtUtGetopt(mainArgc, ppMainArgv, "hval:r:m:")) != -1) {
        switch (mainArgvTemp) {
        case 'v':
            printf("CUnit Version:2.1-3\n");
            ret = -1;
            goto end;
            break;
        case 'a':
            printf("Run all CUnit Test\n");
            gFwtUtCfg.flag = FWT_UT_RUN_ALL_SUITE;
            break;
        case 'l':
            printf("Run CUnit Test loop %d\n", atoi(optarg));
            gFwtUtCfg.runLoop = atoi(optarg);
            break;
        case 'r':
            printf("Run CUnit Test name %s\n", optarg);
            gFwtUtCfg.pCunitName = optarg;
            gFwtUtCfg.flag = FWT_UT_RUN_SIGNAL_SUITE;
            break;
        case 'h':
        default:
            printf("The help info:\n"
                   "    -h    show help info\n"
                   "    -v    show version\n"
                   "    -a    run all Cunit suite\n"
                   "    -l    run Cunit suite loop. -l 2\n"
                   "    -r    run Cunit suite name. -r xxxx\n");
            ret = -1;
            goto end;
            break;
        }
    }
end:
    optind = 1;
    return ret;
}

/**
 * @brief   测试入口，执行./test 套件名称 可以运行对应套件，执行./test all 可以运行所有套件
 * @param:  [in]   char *argv[] 需要进行测试的套件
 * @param:  [in]   int argc     执行测试用例时输入参数的个数，系统自动生成
 * @return  [out]  无
 * @warning 可重入
 * @note    新生成函数
 */
S32 main(int argc, char *argv[])
{
    U32 i = 0;
    S32 rc = 0;
    U32 suitesnum = 0;
    FILE *ResultFile;
    
    rc = fwtUtArgvHandle(argc, argv);
    if (rc == -1) {
        goto end;
    }
    
    ///< 记录总的套件数量
    while(gUtSuites[i].pName != NULL) {
        i++;
    }
    suitesnum = i;

    ///< 初始化测试注册表
    if(CU_initialize_registry()) {
        printf("\nInitialization of Test Registry failed.");
    } else {
        rc = fwtAddTests();
        if(rc<0) {
            printf("Add test failed!");
            goto end;
        }

        ///< 如果没有输入参数，则执行交互式测试接口，由用户选择想要测试的套件和用例
        if(argc == 1) {        
            CU_console_run_tests();
            CU_cleanup_registry();
            goto end;
        }
        
        ///< 首先inactive所有套件
        ///< 然后找出与输入名称一致的套件，将之active        
        if (gFwtUtCfg.flag == FWT_UT_RUN_SIGNAL_SUITE) {
            fwtRunSuite(suitesnum, 1, &gFwtUtCfg.pCunitName);
        }

        ///< 设置输出文件的名称，并通过automated接口执行测试
        CU_set_output_filename("ps3-firmware");      
        (void)CU_list_tests_to_file();
        
        for (i = 0; i < gFwtUtCfg.runLoop; i++) {
            printf("Cunit run loop(%d) start\n", i);
            CU_automated_run_tests();
            CU_print_run_results(ResultFile);
            fwtPrintResults();
            printf("Cunit run loop(%d) end\n", i);
        }
        
        ///< 清理测试注册表
        CU_cleanup_registry();
    }

end:
    return 0;
}
